import tkinter as tk
from tkinter import ttk
import os
import json
from datetime import datetime
from tkinter import messagebox  # 在文件顶部导入部分添加这行
# 修正类结构（删除错误位置的代码，将功能移至正确位置）
class HistoryWindow:
    _instance = None  # 类变量用于存储单例
    SELECTED_HISTORY_FILE = os.path.join("configs_all", "selected_history.json")
    MAX_HISTORY_ITEMS = 150  # 扩展原始保存数量到150条
    
    @classmethod
    def _check_history_file(cls):
        """检查历史文件路径"""
        print(f"历史文件完整路径: {os.path.abspath(cls.SELECTED_HISTORY_FILE)}")
        print(f"历史文件是否存在: {os.path.exists(cls.SELECTED_HISTORY_FILE)}")
        if os.path.exists(cls.SELECTED_HISTORY_FILE):
            try:
                with open(cls.SELECTED_HISTORY_FILE, 'r', encoding='utf-8') as f:
                    data = json.load(f)
                print(f"历史文件内容: {data}")
            except Exception as e:
                print(f"读取历史文件失败: {str(e)}")

    def __new__(cls, parent):
        # 如果已经存在实例，就把它提升到前台
        if cls._instance is not None:
            if cls._instance.window.winfo_exists():  # 检查窗口是否仍然存在
                cls._instance.window.lift()  # 将窗口提升到前台
                cls._instance.window.focus_force()  # 强制获取焦点
                return cls._instance  # 返回现有实例而不是None
            else:
                cls._instance = None  # 如果窗口已被销毁，清除实例
        
        # 创建新实例
        instance = super().__new__(cls)
        cls._instance = instance
        return instance
    def __init__(self, parent):
        # 在初始化时检查历史文件
        self._check_history_file()
        
        # 如果是已存在的实例且窗口已创建，直接返回
        if hasattr(self, 'window') and self.window.winfo_exists():
            return
        
        self.window = tk.Toplevel(parent)
        self.window.title("选中历史记录")
        self.window.geometry("600x500")
        
        # 创建主框架
        main_frame = ttk.Frame(self.window)
        main_frame.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
        
        # 修改说明标签，添加使用说明
        title_label = ttk.Label(
            main_frame, 
            text="最近20条选中的提示词记录", 
            font=("Arial", 12, "bold")
        )
        title_label.pack(pady=(10,5))
        
        # 添加使用说明标签
        instruction_text = ("使用说明：\n"
                          "1、单击一条提示词，主界面会自动选中并可使用。\n"
                          "2、双击一条提示词，主界面会自动选中，本界面关闭。\n"
                          "3、右键双击任意位置可关闭本界面。")
        instruction_label = ttk.Label(
            main_frame,
            text=instruction_text,
            justify=tk.LEFT,
            wraplength=550  # 设置文本换行宽度
        )
        instruction_label.pack(pady=(0,10))
        
        # 创建列表框架
        list_frame = ttk.Frame(main_frame)
        list_frame.pack(fill=tk.BOTH, expand=True)
        
        # 创建按钮框架
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=tk.X, pady=10)
        
        # 添加清空历史记录按钮
        clear_button = ttk.Button(
            button_frame,
            text="清空历史记录",
            command=self.clear_history
        )
        clear_button.pack(side=tk.RIGHT, padx=10)
        
        # 创建列表框
        self.history_list = ttk.Treeview(
            list_frame, 
            columns=("时间", "文件名"), 
            show="headings",
            height=15
        )
        
        # 设置列宽
        self.history_list.column("时间", width=200)
        self.history_list.column("文件名", width=300)
        
        self.history_list.heading("时间", text="选中时间")
        self.history_list.heading("文件名", text="提示词文件")
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(
            list_frame, 
            orient="vertical", 
            command=self.history_list.yview
        )
        self.history_list.configure(yscrollcommand=scrollbar.set)
        
        # 使用pack布局管理器
        self.history_list.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 在创建列表框后添加选中事件绑定
        self.history_list.bind('<<TreeviewSelect>>', self.on_item_selected)
        self.history_list.bind('<Double-1>', self.on_item_double_click)
        
        # 保存父窗口引用，用于更新主界面
        self.parent = parent
        
        # 定义关闭窗口的函数
        def close_window(event):
            self._on_closing()
        
        # 为窗口和所有子控件绑定右键双击事件
        self.window.bind("<Double-Button-3>", close_window)
        main_frame.bind("<Double-Button-3>", close_window)
        title_label.bind("<Double-Button-3>", close_window)
        instruction_label.bind("<Double-Button-3>", close_window)
        list_frame.bind("<Double-Button-3>", close_window)
        button_frame.bind("<Double-Button-3>", close_window)
        self.history_list.bind("<Double-Button-3>", close_window)
        clear_button.bind("<Double-Button-3>", close_window)
        scrollbar.bind("<Double-Button-3>", close_window)
        
        # 设置窗口最小尺寸
        self.window.minsize(500, 400)
        
        # 加载历史记录
        self.load_history()
        
        # 绑定窗口关闭事件
        self.window.protocol("WM_DELETE_WINDOW", self._on_closing)
        
        # 设置模态窗口
        self.window.transient(parent)
        self.window.grab_set()
    
    def _on_closing(self):
        """窗口关闭时的处理"""
        HistoryWindow._instance = None  # 清除实例引用
        self.window.destroy()
    
    def load_history(self):
        """加载选中历史记录"""
        # 清空现有列表
        for item in self.history_list.get_children():
            self.history_list.delete(item)
        
        # 加载选中历史
        if not os.path.exists(self.SELECTED_HISTORY_FILE):
            print(f"历史文件不存在: {self.SELECTED_HISTORY_FILE}")
            return
        
        try:
            print(f"正在加载历史文件: {self.SELECTED_HISTORY_FILE}")
            with open(self.SELECTED_HISTORY_FILE, 'r', encoding='utf-8') as f:
                history_data = json.load(f)
                print(f"加载到的历史数据: {history_data}")
                
            if not history_data:
                print("历史数据空")
                return
            
            # 创建一个字典来存储每个文件名最新的记录
            # 修改排序逻辑确保最新记录在前
            # 先按时间戳正序排列（最旧在前），然后遍历保留最新记录
            sorted_history = sorted(
                history_data,
                key=lambda x: x['timestamp'],
                reverse=False  # 改为正序排列
            )
            
            latest_records = {}
            # 按正序遍历，后面的记录会覆盖前面的（即时间较晚的会保留）
            for record in sorted_history:
                filename = record['filename']
                latest_records[filename] = record
            
            # 再次倒序排序显示最新的记录在最上方
            sorted_records = sorted(
                latest_records.values(),
                key=lambda x: x['timestamp'],
                reverse=True  # 最终显示时倒序排列
            )
            
            # 显示去重后的记录
            for record in sorted_records:
                date_str = record['timestamp']
                filename = record['filename']
                print(f"插入记录: {date_str} - {filename}")
                self.history_list.insert("", "end", values=(date_str, filename))
                
        except Exception as e:
            print(f"加载选中历史记录失败: {str(e)}")
            import traceback
            print(traceback.format_exc())

    @classmethod
    def add_selected_history(cls, filename):
        """添加新的选中历史记录"""
        # 确保目录存在
        os.makedirs(os.path.dirname(cls.SELECTED_HISTORY_FILE), exist_ok=True)
        
        # 读取现有历史记录
        history_data = []
        if os.path.exists(cls.SELECTED_HISTORY_FILE):
            try:
                with open(cls.SELECTED_HISTORY_FILE, 'r', encoding='utf-8') as f:
                    history_data = json.load(f)
            except:
                history_data = []
        
        # 添加新记录
        new_record = {
            'filename': filename,
            'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        }
        
        # 添加新记录并保持最近20条
        history_data.append(new_record)
        # 修改保存逻辑（约232-235行）
        # 保持原始记录数量为50条，给去重留出空间
        if len(history_data) > cls.MAX_HISTORY_ITEMS:
            history_data = history_data[-cls.MAX_HISTORY_ITEMS:]  # 改为保留最后50条
        
        # 保存到文件
        try:
            with open(cls.SELECTED_HISTORY_FILE, 'w', encoding='utf-8') as f:
                json.dump(history_data, f, ensure_ascii=False, indent=4)
        except Exception as e:
            print(f"保存选中历史记录失败: {str(e)}")

    def on_item_selected(self, event):
        """处理列表项被选中的事件"""
        # 获取选中项
        selection = self.history_list.selection()
        if not selection:
            return
            
        # 获取选中项的文件名
        item = self.history_list.item(selection[0])
        filename = item['values'][1]  # 文件名在第二列
        
        try:
            # 通过 root 访问 app 实例
            if hasattr(self.parent, 'app'):
                # 更新主界面文件列表选中状态
                group = self.parent.app.data_manager.get_group_by_filename(filename)
                if group:
                    # 先选中对应的分组
                    groups = self.parent.app.group_list.get(0, tk.END)
                    if group in groups:
                        group_index = groups.index(group)
                        self.parent.app.group_list.select_clear(0, tk.END)
                        self.parent.app.group_list.select_set(group_index)
                        # 加载该分组的文件
                        self.parent.app.load_files_from_group(None)
                        
                        # 在文件列表中选中对应文件
                        files = self.parent.app.file_list.get(0, tk.END)
                        if filename in files:
                            file_index = files.index(filename)
                            self.parent.app.file_list.select_clear(0, tk.END)
                            self.parent.app.file_list.select_set(file_index)
                            # 加载文件内容
                            self.parent.app.load_file(None)
        except Exception as e:
            print(f"更新主界面选中状态失败: {str(e)}")
            import traceback
            print(traceback.format_exc())

    def on_item_double_click(self, event):
        """处理列表项被双击的事件"""
        # 获取选中项
        selection = self.history_list.selection()
        if not selection:
            return
            
        # 获取选中项的文件名
        item = self.history_list.item(selection[0])
        filename = item['values'][1]  # 文件名在第二列
        
        try:
            # 通过 root 访问 app 实例
            if hasattr(self.parent, 'app'):
                # 更新主界面文件列表选中状态
                group = self.parent.app.data_manager.get_group_by_filename(filename)
                if group:
                    # 先选中对应的分组
                    groups = self.parent.app.group_list.get(0, tk.END)
                    if group in groups:
                        group_index = groups.index(group)
                        self.parent.app.group_list.select_clear(0, tk.END)
                        self.parent.app.group_list.select_set(group_index)
                        # 加载该分组的文件
                        self.parent.app.load_files_from_group(None)
                        
                        # 在文件列表中选中对应文件
                        files = self.parent.app.file_list.get(0, tk.END)
                        if filename in files:
                            file_index = files.index(filename)
                            self.parent.app.file_list.select_clear(0, tk.END)
                            self.parent.app.file_list.select_set(file_index)
                            # 加载文件内容
                            self.parent.app.load_file(None)
                            
                            # 关闭历史记录窗口
                            self._on_closing()
                            
        except Exception as e:
            print(f"更新主界面选中状态失败: {str(e)}")
            import traceback
            print(traceback.format_exc())

    def clear_history(self):
        """清空历史记录"""
        try:
            # 清空 JSON 文件
            with open(self.SELECTED_HISTORY_FILE, 'w', encoding='utf-8') as f:
                json.dump([], f, ensure_ascii=False, indent=4)
            
            # 清空列表显示
            for item in self.history_list.get_children():
                self.history_list.delete(item)
                
            # 显示成功消息
            tk.messagebox.showinfo("成功", "历史记录已清空")
            
        except Exception as e:
            tk.messagebox.showerror("错误", f"清空历史记录失败: {str(e)}")